package com.dingreading.cloud.ssxcx.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.dingreading.cloud.common.base.R;
import com.dingreading.cloud.common.util.KitUtil;
import com.dingreading.cloud.common.util.PageUtil;
import com.dingreading.cloud.common.util.MstXcxClassType;
import com.dingreading.cloud.common.util.aliyun.MstCdnUtil;
import com.dingreading.cloud.ssxcx.dto.MembersDto;
import com.dingreading.cloud.ssxcx.dto.XcxLessonMaterialsDto;
import com.dingreading.cloud.ssxcx.dto.XcxStudentQuizAnswersDto;
import com.dingreading.cloud.ssxcx.entity.XcxAnswersPandect;
import com.dingreading.cloud.ssxcx.entity.XcxStudentLearningProgress;
import com.dingreading.cloud.ssxcx.entity.XcxStudentQuizAnswers;
import com.dingreading.cloud.ssxcx.entity.table.XcxStudentQuizAnswersTableDef;
import com.dingreading.cloud.ssxcx.mapper.XcxStudentQuizAnswersMapper;
import com.dingreading.cloud.ssxcx.service.*;
import com.dingreading.cloud.ssxcx.util.DataProcessUtils;
import com.dingreading.cloud.ssxcx.util.XcxEntityUtils;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryCondition;
import com.mybatisflex.core.query.QueryWrapper;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 小程序学生答题记录表 服务层实现。
 *
 * @author EDY
 * @since 2025-08-15
 */
@Service
public class XcxStudentQuizAnswersServiceImpl extends BaseServiceImpl<XcxStudentQuizAnswersMapper, XcxStudentQuizAnswers, XcxStudentQuizAnswersTableDef> implements XcxStudentQuizAnswersService {
    @Resource
    private DataProcessUtils dataUtils;
    @Resource
    private XcxLessonMaterialsService xcxLessonMaterialsService;
    @Resource
    private XcxAnswersPandectService xcxAnswersPandectService;
    @Resource
    private XcxLessonQuizOptionsService xcxLessonQuizOptionsService;
    @Resource
    private XcxStudentLearningProgressService xcxStudentLearningProgressService;

    @Override
    protected XcxStudentQuizAnswersTableDef getTable() {
        return XcxStudentQuizAnswersTableDef.xcxStudentQuizAnswers;
    }

    @Override
    public R<Object> checkCorrect(String agencyUid, String storeUid, String studentUid, String subjectLessonUid) {
        if (StringUtils.isBlank(agencyUid))
            return R.fail("伙伴uid为空！");
        if (StringUtils.isBlank(storeUid))
            return R.fail("门店uid为空！");
        if (StringUtils.isBlank(studentUid))
            return R.fail("学生uid为空！");
        if (StringUtils.isBlank(subjectLessonUid))
            return R.fail("课节uid为空！");

        R<Object> ret = dataUtils.checkStudentUid(agencyUid, studentUid);
        if (R.isError(ret))
            return ret;

        QueryCondition baseCondition = QueryCondition.createEmpty()
                .and(table.agencyUid.eq(agencyUid))
                .and(table.storeUid.eq(storeUid))
                .and(table.studentUid.eq(studentUid))
                .and(table.subjectLessonUid.eq(subjectLessonUid));

        long l = getMapper().selectCountByCondition(baseCondition);
        boolean isFirstEntry = (l == 0); // 如果总数为0，则为第一次进入
        boolean exists = false;

        if (!isFirstEntry) {
            XcxAnswersPandect pandect = xcxAnswersPandectService.getLate(studentUid, subjectLessonUid);
            if (pandect != null){
                exists = pandect.getIsAllCorrect() == 1;
            }
        }
        JSONObject result = new JSONObject();
        if (isFirstEntry) {
            // 如果没有答题记录
            result.put("isAllCorrect", false);
            result.put("isFirstEntry", true);
        } else {
            result.put("isFirstEntry", false);
            result.put("isAllCorrect", exists);
        }
        return R.ok(result);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public R<Object> submitStudentQuizAnswers(
            String agencyUid, String storeUid,
            String subjectLessonUid, String studentUid, String optionItems
    ) {
        if (StringUtils.isBlank(agencyUid))
            return R.fail("伙伴uid为空！");
        if (StringUtils.isBlank(storeUid))
            return R.fail("门店uid为空！");
        if (StringUtils.isBlank(studentUid))
            return R.fail("学生uid为空！");
        if (StringUtils.isBlank(subjectLessonUid))
            return R.fail("课程uid为空！");
        if (StringUtils.isBlank(optionItems))
            return R.fail("选项为空！");

        R<Object> ret = dataUtils.checkStudentUid(agencyUid, studentUid);
        if (R.isError(ret))
            return ret;

        MembersDto membersDto = (MembersDto) ret.getData();
        String studentName = membersDto.getMemberName();
        String phone = membersDto.getMob();

        List<XcxStudentQuizAnswers> newItems = new ArrayList<>();
        try {
            // 2. 解析并校验JSON内容
            newItems = JSONObject.parseArray(optionItems, XcxStudentQuizAnswers.class);
            R<Object> validationResult = validateItems(newItems);
            if (R.isError(validationResult)) {
                return validationResult;
            }
        } catch (Exception e) {
            return R.fail("JSON格式错误或数据不符合预期: " + e.getMessage());
        }

        Map<String, String> materialUids = dataUtils.getLessonMaterialUids(subjectLessonUid, MstXcxClassType.INCLASS.getType());
        String projectUid = materialUids.get(DataProcessUtils.KEY_PROJECT_UID);
        String stageUid = materialUids.get(DataProcessUtils.KEY_STAGE_UID);

        List<String> optionUids = newItems.stream().map(XcxStudentQuizAnswers::getStudentOptionUid).collect(Collectors.toList());
        List<String> qustionUids = newItems.stream().map(XcxStudentQuizAnswers::getQuestionUid).collect(Collectors.toList());
        Map<String, Boolean> correctMap = xcxLessonQuizOptionsService.listByOptionUids(optionUids);

        List<XcxStudentQuizAnswers> xcxAnswersList = new ArrayList<>();
        // 保存错误题目的questionUid
        List<String> mistakeQuestionUids = new ArrayList<>();
        List<XcxStudentLearningProgress> Progresses = new ArrayList<>();
        String versionUid = KitUtil.getUuid();

        for (int i = 0; i < newItems.size(); i++) {
            XcxStudentQuizAnswers answer = newItems.get(i);
            System.out.println("answer = " + answer);
            Boolean b = correctMap.get(answer.getStudentOptionUid());
            if (b == null) {
                return R.fail("第" + (i + 1) + "题正确答案不存在！");
            }
            answer.setIsCorrect(b ? 1 : 0);

            // 如果b为false，说明学生选择的答案是错误的
            if (!b) {
                mistakeQuestionUids.add(answer.getQuestionUid()); // 将当前题目的questionUid加入到错误列表
            }

            XcxStudentQuizAnswers xcxAnswers = XcxEntityUtils.newAnswersBean(
                    answer, agencyUid, storeUid, subjectLessonUid,
                    studentUid, studentName, phone, projectUid, stageUid, versionUid
            );

            XcxStudentLearningProgress progress = XcxEntityUtils.newProgressBean(
                    agencyUid, storeUid, studentUid, studentName, phone,
                    answer.getQuestionUid(), null, answer.getStudentOptionUid(),
                    subjectLessonUid, MstXcxClassType.INCLASS.getType(), projectUid, stageUid, versionUid
            );

            xcxAnswersList.add(xcxAnswers);
            Progresses.add(progress);
        }

        QueryCondition condition = QueryCondition.createEmpty()
                .and(table.studentUid.eq(studentUid))
                .and(table.questionUid.in(qustionUids))
                .and(table.enabled.eq(1));
        List<XcxStudentQuizAnswers> oldStudentQuizAnswers = getMapper().selectListByCondition(condition);
        if (CollectionUtils.isNotEmpty(oldStudentQuizAnswers)) {
            oldStudentQuizAnswers.forEach(old -> {old.setEnabled(0);});
            boolean updateOldAnswers = updateBatch(oldStudentQuizAnswers);
            if (!updateOldAnswers) {
                throw new RuntimeException("更新旧记录失败！");
            }
        }

        // 保存学习轨迹
        boolean saveProgress = xcxStudentLearningProgressService.saveBatch(Progresses);
        if (!saveProgress) {
            throw new RuntimeException("保存学习轨迹失败！");
        }

        boolean saveNewAnswers = saveBatch(xcxAnswersList);
        if (!saveNewAnswers) {
            throw new RuntimeException("保存新记录失败！");
        }
        boolean isAllCorrect = CollectionUtils.isEmpty(mistakeQuestionUids);

        XcxAnswersPandect pandect = XcxEntityUtils.newAnswersPandect(studentUid, studentName, subjectLessonUid, versionUid, isAllCorrect);
        boolean savePandect = xcxAnswersPandectService.save(pandect);
        if (!savePandect) {
            throw new RuntimeException("保存答题总况失败！");
        }

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("isAllCorrect", isAllCorrect);
        jsonObject.put("mistakeQuestionUids", mistakeQuestionUids);
        return R.ok(jsonObject);
    }

    @Override
    public R<Object> getMistakeQuestions(String agencyUid, String storeUid, String studentUid, String subjectLessonUid, List<String> questionUids, String ip) {
        if (StringUtils.isBlank(agencyUid))
            return R.fail("伙伴uid为空！");
        if (StringUtils.isBlank(storeUid))
            return R.fail("门店uid为空！");
        if (StringUtils.isBlank(studentUid))
            return R.fail("学生uid为空！");
        if (StringUtils.isBlank(subjectLessonUid))
            return R.fail("课节uid为空！");
        if (CollectionUtils.isEmpty(questionUids))
            return R.fail("题目uid为空！");

        List<XcxLessonMaterialsDto> list = xcxLessonMaterialsService.getMistakeQuestions(subjectLessonUid, questionUids);

        if (CollectionUtils.isNotEmpty(list)) {
            long expire = MstCdnUtil.getVideoExpire();
            // 使用 forEach 遍历列表，同时处理 urls 和 quizOptions
            list.forEach(materialsDto -> {
                // 1. 处理 urls
                if (CollectionUtils.isNotEmpty(materialsDto.getUrls())) {
                    materialsDto.getUrls().stream()
                            .filter(fileDto -> StringUtils.isNotBlank(fileDto.getUrl()))
                            .forEach(fileDto -> fileDto.setUrl(dataUtils.getXcxUrl(fileDto.getUrl(), ip, expire)));
                }

                // 2.打乱 quizOptions
                if (CollectionUtils.isNotEmpty(materialsDto.getQuizOptions())) {
                    Collections.shuffle(materialsDto.getQuizOptions());
                }
            });
        }

        return R.ok(list);
    }

    @Override
    public Page<XcxStudentQuizAnswersDto> pageListMistake(PageUtil pageUtil, String agencyUid, String storeUid, String studentUid, String projectUid) {
        QueryCondition condition = QueryCondition.createEmpty()
                .and(table.agencyUid.eq(agencyUid))
                .and(table.storeUid.eq(storeUid))
                .and(table.studentUid.eq(studentUid))
                .and(table.isCorrect.eq(0));
        if (StringUtils.isNotBlank(projectUid))
            condition.and(table.projectUid.eq(projectUid));
        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition)
                .orderBy(table.id.desc());
        return getMapper().paginateWithRelationsAs(pageUtil.getPageValue(), pageUtil.getRows(), wrapper, XcxStudentQuizAnswersDto.class);
    }

    private R<Object> validateItems(List<XcxStudentQuizAnswers> newItems) {
        for (int i = 0; i < newItems.size(); i++) {
            XcxStudentQuizAnswers answer = newItems.get(i);
            if (StringUtils.isBlank(answer.getQuestionUid()))
                return R.fail("第" + (i + 1) + "题题目为空！");
            if (StringUtils.isBlank(answer.getStudentOptionUid()))
                return R.fail("第" + (i + 1) + "题答案为空！");
        }
        return R.ok();
    }
}
